#include <iostream>
#include "../comm/logger.hpp"
#include "../comm/util.hpp"
#include  <fcntl.h>
#include <sys/wait.h>
  
namespace build{
   class Complie{
   public:
    static bool complieExe(const std::string& filename){
     //创建一个子进程，让其进行程序替换，调用gcc编译器帮助我们去完成源文件的编译工作
     //1.创建一个存放编译错误信息的文件:直接打开文件，不存在则创建
     umask(0);
     int error_fd = open( (helper::PathFile::getCompileError(filename)).c_str() , O_CREAT|O_WRONLY , 0644 );
     int pid = fork();
     if(pid <0 ){
      //孩子，你连子进程都没有创建成功，回家吧，好不好
      DLOG("尝试编译时，子进程创建失败!");
      return false;
     }
     else if(pid == 0){
      //子进程
      /*************************
      *使用子进程进行程序替换，以此编译源文件
      *编译源文件可能成功，也可能失败，成功无所谓，失败我们要获取失败的原因，比如:出现未定义变量之类云云
      **************************/

      //2.对新打开的文件进行重定向，将标准错误重定向我们的编译错误文件当中
      dup2(error_fd,2);
      //3.开始进行程序替换，程序替换后，一切正常，不会回来！若失败了，则会回来
      execlp("g++","g++","-o",helper::PathFile::getTatget(filename).c_str(),
      helper::PathFile::getSrc(filename).c_str(),"-D", "COMPILER_ONLINE","-std=c++11",nullptr/*用nullptr标志多参数的结尾，切不可粗心大意遗漏*/);
      ELOG("编译失败,可能是g++参数错误");
      exit(2);
     }
     else{ 
      waitpid(pid,nullptr,0);
      close(error_fd);
      if( helper::FileUtil::isFileExists(helper::PathFile::getTatget(filename)) ){
        ILOG("编译成功,可执行程序已被创建");
        return true;
      }
      ELOG("编译失败，没有形成可执行程序!");
      return false;
     }
    }
   };
}//完美